package com.googlecode.jerato.library.store;

import java.sql.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import com.googlecode.jerato.core.Service;
import com.googlecode.jerato.core.store.StoreTransaction;
import com.googlecode.jerato.library.SystemException;
import com.googlecode.jerato.library.SystemService;
import com.googlecode.jerato.library.SystemSettings;
import com.googlecode.jerato.library.SystemSettingsKeys;
import com.googlecode.jerato.library.ValueUtility;

public class StoreTransactionService implements Service{

	protected String _jdbcUrl;
	protected String _jdbcUser;
	protected String _jdbcPassword;
	protected String _jdbcDriver;
	protected Map _transactionCache = new HashMap();

	public StoreTransactionService(){
	}

	public static StoreTransactionService getInstance(){
		return (StoreTransactionService)SystemService.getInstance().getService("transactionService");
	}

	public void startup(){
		_jdbcUrl = SystemSettings.getSystemString(SystemSettingsKeys.DATABASE_URL);
		_jdbcUser = SystemSettings.getSystemString("DatabaseUser");
		_jdbcPassword = SystemSettings.getSystemString("DatabasePassword");
		_jdbcDriver = SystemSettings.getSystemString("DatabaseDriver");

		if(ValueUtility.isEmpty(_jdbcDriver)){
			throw new SystemException("JDBC driver name is empty.");
		}
		try{
			Class.forName(_jdbcDriver);
		}
		catch(ClassNotFoundException ce){
			throw new SystemException("JDBC driver load failed.", ce);
		}
	}

	public void shutdown(){
		synchronized(_transactionCache){
			for (Iterator itr = _transactionCache.keySet().iterator(); itr.hasNext(); ){
				StoreTransactionImpl transaction = (StoreTransactionImpl)itr.next();
				transaction.end();
			}
			_transactionCache.clear();
		}
	}

	public void release(StoreTransactionImpl transaction){
		synchronized(_transactionCache){
			transaction = (StoreTransactionImpl)_transactionCache.remove(transaction);
			if(transaction != null){
				transaction.end();
			}
		}
	}

	public void remove(StoreTransactionImpl transaction){
		synchronized(_transactionCache){
			_transactionCache.remove(transaction);
		}
	}

	public StoreTransactionImpl createTransaction(){

		Connection conn = null;
		try{
			conn = DriverManager.getConnection(_jdbcUrl, _jdbcUser, _jdbcPassword);
			conn.setAutoCommit(false);
		}
		catch(SQLException se){
			throw new SystemException("Database connect failed.", se);
		}
		StoreTransactionImpl transaction = new StoreTransactionImpl(this, conn);
		synchronized(_transactionCache){
			_transactionCache.put(transaction, transaction);
		}
		return transaction;
		
	}

	public static StoreTransaction beginTransaction(){
		StoreTransactionService transactionService = SystemService.getInstance().getTransactionService();
		return transactionService.createTransaction();
	}
	
	public static void endTransaction(StoreTransaction transaction){
		if(transaction != null){
			transaction.end();
		}
	}
}
